import { App, cloneVNode, computed, defineComponent, getCurrentInstance, onMounted, PropType, ref, Teleport, TeleportProps, Transition } from 'vue'
import { getComponent, getSlot } from '../_util/props-util'

const preCls = 'x-drawer'

const Drawer = defineComponent({
  name: preCls,
  props: {
    title: String,
    visible: Boolean,
    width: { type: [Number, String], default: 396 },
    mask: { type: Boolean, default: true },
    maskClosable: { type: Boolean, default: true },
    to: { type: [String, Object] as PropType<TeleportProps['to']>, default: 'body' }
  },
  inheritAttrs: false,
  emits: ['update:visible'],
  setup(props, { attrs, emit }) {
    const { proxy: vm } = getCurrentInstance()

    function onClose() {
      setVisible(false)
    }
    function onMaskClick() {
      if (!props.maskClosable) return
      onClose()
    }
    function setVisible(visible: Boolean) {
      emit('update:visible', visible)
    }
    
    const isMounted = ref(false)
    onMounted(() => {
      isMounted.value = true
    })

    // // 禁用 parent 滚动
    // let parentOverflow: string  // undefined 是必要的
    // watchEffect(() => {
    //   const { visible, to } = props
    //   const parentEle = typeof to === 'string'
    //     ? document.querySelector(to)
    //     : typeof to === 'function' ? to() : to
    //   if (!parentEle) return
      
    //   if (visible) {
    //     parentOverflow = parentEle.style.overflow
    //     parentEle.style.overflow = 'hidden'
    //   } else if (parentOverflow !== 'hidden') {
    //     parentEle.style.overflow = parentOverflow
    //   }
    // })
    
    const headerRef = computed(() => {
      let title = getComponent(vm, 'title')
      let header = getComponent(vm, 'header')?.[0]
      if (!header && !title) return undefined
      const extraProps = { class: `${preCls}_header` }
      if (header) {
        header = cloneVNode(header, extraProps)
      } else {
        header = <div { ...extraProps }><div class={`${preCls}_title`}>{ title }</div></div>
      }
      return header
    })

    const footerRef = computed(() => {
      const footer = getComponent(vm, 'footer')
      if (!footer) return undefined
      return <div class={`${preCls}_footer`}>{ footer }</div>
    })

    return () => {
      if (!isMounted.value) return
      
      const { mask: hasMask, to, visible, width } = props
      const body = <div class={`${preCls}_body`}>{ getSlot(vm) }</div>
      const mask = hasMask ? <div v-show={visible} class={`${preCls}_mask`} onClick={onMaskClick} /> : undefined

      const clazz = [preCls, { [`${preCls}-open`]: visible, [`${preCls}-glass`]: visible }]

      return (
        <Teleport to={to}>
          <div class={clazz} { ...attrs }>
            <Transition name='fade'>
              { mask }
            </Transition>
            <div class={`${preCls}_wrapper`} style={{ width: width + 'px' }}>
              { headerRef.value }
              { body }
              { footerRef.value }
            </div>
          </div>
        </Teleport>
      )
    }
  }
})

Drawer.install = (app: App) => {
  app.component(Drawer.name, Drawer)
}

export default Drawer